【Unity】Unity使用动画实现场景转换 |
您所在的位置:网站首页 › unity 加载场景后物理组件异常 › 【Unity】Unity使用动画实现场景转换 |
文章目录
前言一、制作LevelLoader二、制作相应场景转换特效1.淡入淡出效果2.圆形擦除效果3.Logo旋转效果
三、编写控制场景转换效果脚本1.同步加载场景(1)将控制脚本添加进LevelLoader中。(2)创建一个新场景,并将LevelLoader添加进其中。(3)将场景添加进Build Settings。(4)最终淡入淡出效果。(5)最终圆形擦除效果。(6)最终Logo旋转效果。
2.异步加载场景(1)分析需求。
四、完毕
前言
哈喽,大家好,我是FEZ98. 由于今天需要实现一个小项目中的场景转换效果,于是使用了Animator简单的实现了这个需求,同时也与大家分享一下今日的收获,如果哪里有错误,还望朋友们指正。 使用动画实现简单的场景转换的思路是向场景中添加一个专门处理转换效果的Image(UGUI),同时向其添加一个Animator,向Aniamtor中加入两个State,一个设置为Set as Layer Defalut State,即默认状态,播放进入场景后需要的效果,另一个则设置为关闭场景需要的效果,添加一个转换,并设置相应的参数,这样当我们加载下一场景时,只需要在脚本中设置相应的参数即可调用关闭场景需要的效果。 一、制作LevelLoader首先我们需要制作一个GameObject用来存放场景转换效果所需对象与脚本,同时可以单独加一个Camera用来单独显示转换特效。如下图: 向LevelLoader中添加一个Canvas,命名为Crossfade,添加一个Image,命名为Mask_Img,这个将这个Image设置为全黑色,如下: 扩展: Canvas Group可集中控制整组 UI 元素的某些方面,而无需单独处理每个元素。画布组的属性会影响所在的游戏对象以及所有子对象。 回到正文,在添加完Mask_Img后,我们就可以通过Animator控制其Canvas Group来制作动画了,在Hierarchy选中Crossfade对象,按下Ctrl+6打开Animation。 首先我们用Photoshop制作一张如下的png图片。
对于Logo旋转场景转换的效果步骤大体与圆形擦除一致,以下是LogoRotate_End与LogoRotate_Start的Animation Clip。 这部分我们会在异步加载场景的过程中添加场景转换效果。 首先,我们将Crossfade的Animator设置如下 因为每次新创建一个场景,我们都需要将LevelLoader预制体添加到场景中会比较麻烦,因此我考虑使用单例模式加上DontDestroyOnLoad方法,这样在第一次加载后,LevelLoader就不会被销毁,在后续新添加的场景中自然也不用添加LevelLoader了。之后,我们还希望使用一个LevelLoader就可以使用不同的场景转换动画,这样可以方便我们进行后续新的场景转换动画的添加与使用。于是我们需要添加一个用于控制不同场景转换动画的脚本。 using System.Collections; using System.Collections.Generic; using UnityEngine; public enum Effect //三种场景转换特效 { Crossfade = 0, //淡入淡出 CircleWipe = 1, //圆形擦除 LogoRotate = 2, //Logo旋转 } public class TransitionEffect : MonoBehaviour { private static TransitionEffect _instance; public static TransitionEffect Instance { get { return _instance; } } Animator m_CrossfadeAnim; //淡入淡出 Animator m_CircleWipeAnim; //圆形擦除 Animator m_LogoRotateAnim; //Logo旋转 private void Awake() { if (_instance == null) { DontDestroyOnLoad(this); _instance = this; } else { Destroy(this); } m_CrossfadeAnim = GameObject.Find("Crossfade").GetComponent(); m_CircleWipeAnim = GameObject.Find("CircleWipe").GetComponent(); m_LogoRotateAnim = GameObject.Find("LogoRotate").GetComponent(); } /// /// 播放指定类型场景转换结束动画 /// /// 场景转换特效类型 public void HandleAllAnimationEnd(Effect effect) { switch (effect) { case Effect.Crossfade: SetTransitionEffectEnd(m_CrossfadeAnim); break; case Effect.CircleWipe: SetTransitionEffectEnd(m_CircleWipeAnim); break; case Effect.LogoRotate: SetTransitionEffectEnd(m_LogoRotateAnim); break; default: break; } } private void SetTransitionEffectEnd(Animator animator) { animator.SetTrigger("End"); Debug.Log("AnimationClip_End is Start!"); } /// /// 播放指定类型场景转换开始动画 /// /// 场景转换特效类型 public void HandleAllAnimationStart(Effect effect) { switch (effect) { case Effect.Crossfade: SetTransitionEffectStart(m_CrossfadeAnim); break; case Effect.CircleWipe: SetTransitionEffectStart(m_CircleWipeAnim); break; case Effect.LogoRotate: SetTransitionEffectStart(m_LogoRotateAnim); break; default: break; } } private void SetTransitionEffectStart(Animator animator) { animator.SetTrigger("Start"); Debug.Log("AnimationClip_Start is Start!"); } /// /// 判断当前动画是否完成播放 /// /// 场景转换特效类型 /// public bool HandleAllAnimationDone(Effect effect) { switch (effect) { case Effect.Crossfade: return IsAnimationClipDone(m_CrossfadeAnim); case Effect.CircleWipe: return IsAnimationClipDone(m_CircleWipeAnim); case Effect.LogoRotate: return IsAnimationClipDone(m_LogoRotateAnim); default: break; } return false; } private bool IsAnimationClipDone(Animator animator) { //normalizedTime:整数部分为状态已循环的次数。小数部分为当前循环的进度百分比 (0-1) if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime private static AsyncLoadLevelManager _instance; public static AsyncLoadLevelManager Instance { get { return _instance; } } public bool LoadAble { get; private set; } //当前是否可以场景转换 private void Awake() { if (_instance == null) { DontDestroyOnLoad(this); _instance = this; } else { Destroy(this); } } private void Start() { LoadAble = true; //初始允许场景转换 } /// /// 使用指定场景转换特效异步加载下一场景 /// /// 下一场景名称 /// 场景转换特效类型 public void LoadNextLevel(string levelName, Effect effect) { if (!LoadAble) { return; } StartCoroutine(LoadLevel(levelName, effect)); } IEnumerator LoadLevel(string levelName, Effect effect) { AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(levelName); //异步加载下一场景 asyncOperation.allowSceneActivation = false; //当allowSceneActivation为false时,asyncOperation.progre会停在0.9并且asyncOperation.isDone也会一直为false LoadAble = false; //当前不允许转换场景 TransitionEffect.Instance.HandleAllAnimationStart(effect); //播放场景转换开始动画 yield return null; while (asyncOperation.progress yield return null; } asyncOperation.allowSceneActivation = true; //允许场景准备就绪后立即激活场景 while (!asyncOperation.isDone) //检查是否已经激活场景 { yield return null; TransitionEffect.Instance.HandleAllAnimationEnd(effect); //播放场景转换结束动画 } while (!TransitionEffect.Instance.HandleAllAnimationDone(effect)) //检查当前动画是否完成播放 { yield return null; } LoadAble = true; //可以继续转换场景 } }之后,我们用一个测试脚本进行方法的调用。 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { private void Update() { if (Input.GetMouseButtonDown(0)) //点击鼠标左键 { AsyncLoadLevelManager.Instance.LoadNextLevel("SceneB", Effect.Crossfade); } else if (Input.GetMouseButtonDown(1)) //点击鼠标右键 { AsyncLoadLevelManager.Instance.LoadNextLevel("SceneC", Effect.CircleWipe); } else if (Input.GetMouseButtonDown(2)) //点击鼠标中键 { AsyncLoadLevelManager.Instance.LoadNextLevel("SceneA", Effect.LogoRotate); } } }最终效果如下: 扩展 背景图片移动 using UnityEngine; using UnityEngine.UI; public class BackgroundMove : MonoBehaviour { public float speed = 0; //移动速度 float pos = 0; //当前位置 private RawImage image; void Start() { image = GetComponent(); } void Update() { pos += speed; if (pos > 1.0F) pos -= 1.0F; image.uvRect = new Rect(pos, 0, 1, 1); } } 四、完毕好啦,以上就是我今天想要分享的内容啦~ 我是FEZ98:https://blog.csdn.net/weixin_43057990 原创不易,若转载请注明出处,感谢大家~ 喜欢我的可以点赞、关注、收藏,最后希望能够对大家有所帮助! |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |